package com.loveprogrammer.network;

import com.alibaba.fastjson2.JSON;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.loveprogrammer.command.anotation.TagListener;
import com.loveprogrammer.command.client.ClientLoginTag;
import com.loveprogrammer.command.client.ClientMenuTag;
import com.loveprogrammer.command.client.ClientTopic;
import com.loveprogrammer.console.ConsolePrint;
import com.loveprogrammer.constants.CommonValue;
import com.loveprogrammer.dto.base.RequestBase;
import com.loveprogrammer.dto.base.StringRequest;
import com.loveprogrammer.handler.HandlerFactory;
import com.loveprogrammer.listener.INetworkEventListener;
import com.loveprogrammer.pojo.StringMessage;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class NetworkClientListener implements INetworkEventListener {

    protected static final Logger logger = LoggerFactory.getLogger(NetworkClientListener.class);

    private NetworkClientListener(){

    }

    private static final NetworkClientListener instance = new NetworkClientListener();

    public static NetworkClientListener getInstance(){
        return instance;
    }


    private final ThreadPoolExecutor executor = new ThreadPoolExecutor(
            2,
            2,
            0L,
            TimeUnit.SECONDS,
            new LinkedBlockingQueue<>(1024),
            new ThreadFactoryBuilder()
                    .setNameFormat("worker-pool-%d").build(),
            new ThreadPoolExecutor.CallerRunsPolicy()
    );

    /***
     * 同客户端转发
     * @param ctx
     * @param topic
     * @param tag
     * @param msg
     */
    public void forward(ChannelHandlerContext ctx, int topic, int tag, String msg) {
        StringMessage data = new StringMessage();
        data.setTopicId(topic);
        data.setTagId(tag);
        data.setBody(msg);
        channelRead(ctx,data);
    }

    @Override
    public void onConnected(ChannelHandlerContext ctx) {

    }

    @Override
    public void onDisconnected(ChannelHandlerContext ctx) {

    }

    @Override
    public void onExceptionCaught(ChannelHandlerContext ctx, Throwable throwable) {

    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, StringMessage msg) {
        int topicId = msg.getTopicId();
        int tagId = msg.getTagId();
        int statusCode = msg.getStatusCode();

        Object handler = HandlerFactory.handlerMap.get(topicId);
        if (handler == null) {
            logger.warn("未获取到指定的消息监听对象，topicId {}", topicId);
            return;
        }
        String bodyValue = msg.getBody();
        executor.execute(() -> {
            try {
                Class<?> handlerClass = handler.getClass();
                // 找到tag 遍历methods
                Method[] methods = handlerClass.getMethods();
                for (Method method : methods) {
                    TagListener mqListener = method.getAnnotation(TagListener.class);
                    if (tagId == mqListener.tag()) {
                        Class<?> aClass = mqListener.messageClass();
                        String name = aClass.getName();
                        // 先处理基本类型
                        if ("java.lang.String".equals(name)) {
                            method.invoke(handler, ctx, bodyValue);
                        } else if ("java.lang.Long".equals(name)) {
                            Long object = Long.parseLong(bodyValue);
                            method.invoke(handler, ctx, object);
                        } else if ("java.lang.Integer".equals(name)) {
                            Integer object = Integer.parseInt(bodyValue);
                            method.invoke(handler, ctx, object);
                        } else if ("java.lang.Short".equals(name)) {
                            Short object = Short.parseShort(bodyValue);
                            method.invoke(handler, ctx, object);
                        } else if ("java.lang.Byte".equals(name)) {
                            Byte object = Byte.parseByte(bodyValue);
                            method.invoke(handler, ctx, object);
                        } else if ("java.lang.Double".equals(name)) {
                            Double object = Double.parseDouble(bodyValue);
                            method.invoke(handler, ctx, object);
                        } else if ("java.lang.Float".equals(name)) {
                            Float object = Float.parseFloat(bodyValue);
                            method.invoke(handler, ctx, object);
                        }
                        // 转对象类型
                        else {
                            Object object = JSON.parseObject(bodyValue, aClass);
                            if(statusCode != CommonValue.MSG_STATUS_CODE_SUCCESS) {
                                RequestBase base = (RequestBase) object;
                                ConsolePrint.publishMessage(base.getErrorMsg());
                            }
                            method.invoke(handler, ctx, object);
                        }
                        break;
                    }
                }
            } catch (Exception e) {
                logger.error("发生异常", e);
                // 转发到首页
                StringRequest request = new StringRequest();
                request.setContent("发生异常" + e.getMessage());
                forward(ctx, ClientTopic.TOPIC_LOGIN, ClientLoginTag.TAG_LOGIN_REGISTER, JSON.toJSONString(request));
            }
        });

    }
}
